package com.zhny.aiot.leakage.valve.v2.plugin.model;

import com.google.common.collect.ImmutableMap;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.model.IRequestMessage;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.aiot.plugin.v2.gateway.model.NodeV2RequestMessage;
import com.zhny.aiot.plugin.zhnygateway.GatewayEngine;
import com.zhny.aiot.plugin.zhnygateway.device.ZhnyConfig;
import com.zhny.aiot.plugin.zhnygateway.device.ZhnyDevice;
import com.zhny.aiot.plugin.zhnygateway.model.GatewayResponseMessage;
import com.zhny.aiot.plugin.zhnygateway.model.NodeRequestMessage;
import org.pf4j.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class LeakageV2Device extends ZhnyDevice<LeakageValveV2StoreEntry> {
    private static final Logger logger = LoggerFactory.getLogger(LeakageV2Device.class);
    private final Map<String, Integer> CommandOperations;
    public LeakageV2Device(GatewayEngine engine, IDeviceFactory<ZhnyConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super(engine, factory, centerFacilities, entity);
        CommandOperations =  new ImmutableMap.Builder<String, Integer>()
                .put("openValve1", 0x32)
                .put("closeValve1", 0x31)
                .put("openValve2", 0x34)
                .put("closeValve2", 0x33)
                .put("openValve3", 0x36)
                .put("closeValve3", 0x35)
                .put("openValve4", 0x38)
                .put("closeValve4", 0x37)
                .put("queryStatus", 0x39)
                .put("queryVoltage", 0x3A).build();
    }

    @Override
    public void onDecoder(GatewayResponseMessage message) {
        logger.info (message.toString ());
        int type = message.getDeviceType ();
        if(type == 0x01){
            logger.info("---start decoder leakage v2 message---");
            onMessage(message);
        }
        message.getDeviceData ().release ();
    }

    private void onMessage(GatewayResponseMessage message) {
        MessageEntry resultMsg = MessageUtils.createMessageEntry (this.getId ());
        resultMsg.setType(MessageType.RESULT);
        LeakageValveV2StoreEntry storeEntry = new LeakageValveV2StoreEntry ();
        int operation = message.getDeviceOper ();
        if(operation >= 0x31 && operation <= 0x38){
            if(message.getDataLength () == 7){
                resultMsg.setType (MessageType.ERROR);
                resultMsg.setData ("水利机械阀加入任务失败");
                logger.error ("[deviceNo:{},controllerNo:{}] 水利机械阀加入任务[{}]失败"
                        , getConfig ().getAddress (), getConfig ().getChannelNo (), operation);
                nofity (resultMsg);
                return;
            } else if(operation == 0x31){
                storeEntry.setAStatus (false);
                resultMsg.setData (storeEntry);
            } else if(operation == 0x32){
                storeEntry.setAStatus (true);
                resultMsg.setData (storeEntry);
            } else if(operation == 0x33){
                storeEntry.setBStatus (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x34){
                storeEntry.setBStatus (true);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x35){
                storeEntry.setCStatus (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x36){
                storeEntry.setCStatus (true);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x37){
                storeEntry.setDStatus (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x38){
                storeEntry.setDStatus (true);
                resultMsg.setData (storeEntry);
            }
        } else if(operation == 0x39) {
            Boolean valve1Status = message.getDeviceData ().readUnsignedByte ()==1?true:false;
//            storeEntry.setAStatus (valve1Status);
            storeEntry.setAWaterFlow (valve1Status);
            Boolean valve2Status = message.getDeviceData ().readUnsignedByte ()==1?true:false;
//            storeEntry.setBStatus (valve2Status);
            storeEntry.setBWaterFlow (valve2Status);
            Boolean valve3Status = message.getDeviceData ().readUnsignedByte ()==1?true:false;
//            storeEntry.setCStatus (valve3Status);
            storeEntry.setCWaterFlow (valve3Status);
            Boolean valve4Status = message.getDeviceData ().readUnsignedByte ()==1?true:false;
//            storeEntry.setDStatus (valve4Status);
            storeEntry.setDWaterFlow (valve4Status);


            resultMsg.setData (storeEntry);
        }else if(operation == 0x3A){
            storeEntry = new LeakageValveV2StoreEntry ();
            storeEntry.setVoltage (createVol(message.getDeviceData ().readShort ()));
            resultMsg.setData (storeEntry);
        }
        logger.info("leakage valve store[{}]",storeEntry.toString());
        save (storeEntry);
        saveReal (storeEntry);
        nofity (resultMsg);
    }
    private double createVol(short vol)
    {
        return vol / 100.0;
    }

    private NodeRequestMessage encode(long key,Map<String,Object> commandMap){
        for (String id : commandMap.keySet ()){
            if(CommandOperations.containsKey(id)) {
                Integer oper=CommandOperations.get(id);
                int length=4;
                return new NodeV2RequestMessage (getzhnyType() + 128, length, oper, Integer.parseInt(getConfig().getAddress()), key,null);
            }
        }
        return null;
    }

    @Override
    protected NodeRequestMessage onCommand(TaskEntity taskEntity) {
        if(StringUtils.isNullOrEmpty (taskEntity.getMethodName ()))
            return null;


        Map<String,Object> command = new HashMap<String, Object>();
        command.put (taskEntity.getMethodName (),null);
        logger.info ("config address[{}]",Integer.parseInt (getConfig ().getAddress ()));
        return encode (taskEntity.getKey (),command);
    }

    @Override
    protected int getzhnyType() {
        return 0x01;
    }

    @Override
    protected void disposable() {

    }
}
